/*
 * miniPaint - https://github.com/viliusle/miniPaint
 * author: Vilius L.
 */

import config from '../../config.js'
import Base_layers_class from './../base-layers.js';
import File_open_class from '../../modules/file/open.js';
import File_new_class from '../../modules/file/new.js';
import Helper_class from '../../libs/helpers.js';
import { message } from 'antd';

// var template = `
// 	<div class="canvas_navigate_wrapper">
//     <div class="navigate_name" id="navigate_name"></div>
// 	</div>
// 	<div class="canvas_navigate_details">
// 		<div class="details">
// 			<button class="navigate_compare" id="navigate_compare">对比原图(F3)</button>
//       <span class="navigate_pager" id="navigate_pager">0 / 0</span>
// 		</div>
// 		<div class="details" id="navigate_control">
// 			<button class="layer_icon layer_text trn" id="navigate_prev">上一张(F1)</button>
// 			<button class="layer_icon layer_text trn" id="navigate_next">下一张(F2)</button>
// 		</div>
// 	</div>
// `

/**
 * GUI class responsible for rendering preview on right sidebar
 */
class GUI_navigate_class {

	constructor() {
    this.name = 'gui_navigate'
		// document.getElementById('toggle_navigate').innerHTML = template
		this.Base_layers = new Base_layers_class();
    this.is_active = false;
    this.is_compare_visible = false;
    this.pager = {
      index: 0,
      count: 0
    }
    this.on_prev_callback = null;
    this.on_next_callback = null;
    this.on_save_callback = null;
    this.on_change_callback = null;
    this.on_close_callback = null;
    this.compare_root_el = null
    this.compare_module_old = null;
    this.compare_module_new = null;
    this.File_open = new File_open_class();
    this.File_new = new File_new_class();
		this.Helper = new Helper_class();
    this.render_compare()
    this.set_events()
	}

  // 显示导航模块，并加载初始内容
  start(config = {}){
    var mergeConfig = {
      ...{
        index: 0,   // 当前图片索引，从0开始
        count: 0,   // 图片总数
        name: '',  // 图片名称
        url: '',  // 图片地址
        onPrev: () => {}, // 切换上一张事件
        onNext: () => {},  // 切换下一张事件
        onSave: () => {},  // 保存
        onClose: () => {},  // 关闭
      },
      ...config
    }
    this.pager = mergeConfig
    this.on_prev_callback = mergeConfig.onPrev
    this.on_next_callback = mergeConfig.onNext
    this.on_save_callback = mergeConfig.onSave
    this.on_close_callback = mergeConfig.onClose
    this.load_image(mergeConfig.name, mergeConfig.url)
    this.update_pager(mergeConfig.index, mergeConfig.count)
    this.toggle_visible(true)
    document.body.focus()

    !!mergeConfig.showSave ? $('#navigate_save').show() : $('#navigate_save').hide()
    !!mergeConfig.showClose ? $('#navigate_close').show() : $('#navigate_close').hide()
  }

  set_events(){
    // document.getElementById('navigate_compare').addEventListener('click', () => {
    //   if(!this.is_active) return
    //   this.on_compare()
    // }, false)
    document.getElementById('navigate_prev').addEventListener('click', () => {
      if(!this.is_active) return
      this.on_prev()
    }, false)
    document.getElementById('navigate_next').addEventListener('click', () => {
      if(!this.is_active) return
      this.on_next()
    }, false)
    document.getElementById('navigate_save').addEventListener('click', () => {
      if(!this.is_active) return
      this.on_save()
    }, false)
    document.getElementById('navigate_close').addEventListener('click', () => {
      if(!this.is_active) return
      this.on_close()
    }, false)
    document.getElementById('suspend-menu-expand').addEventListener('click', () => {
      $('#sidebar_right').toggleClass('hidden')
    }, false)

		document.addEventListener('keydown', (e) => {
      if(e.key == 'F1' || e.key == 'F3') e.preventDefault() // 阻止默认事件
      else if(e.ctrlKey && e.key === 's') e.preventDefault()
    });

		window.addEventListener('keyup', (e) => {
      if(!this.is_active) return
      
      if(e.key == 'F1') this.on_prev()
      else if(e.key == 'F2') this.on_next()
      // else if(e.key == 'F3') this.on_compare()
      else if(e.ctrlKey && e.key === 's') this.on_save()
      // else if(e.key === 'Escape') this.close_compare()
		});

    // document.getElementById('compare_close').addEventListener('click', () => {
    //   this.close_compare()
    // }, false)
  }

  get_layer_is_image(){
    return config.layer.type == 'image'
  }

  update_pager(index, count){
    var new_pager = {
      index: index === undefined ? this.pager.index : index,
      count: count === undefined ? this.pager.count : count,
    }
    this.pager = new_pager
    document.getElementById('navigate_pager').innerHTML = `${new_pager.index + 1} / ${new_pager.count} 页`
    document.getElementById('navigate-base').style.display = new_pager.count <= 1 ? 'none' : 'flex'
  }

  toggle_visible(is_active){
    is_active = !!is_active
    document.getElementById('navigate-base').style.display = is_active ? 'flex' : 'none'
    this.is_active = is_active
  }

  async load_image(name, url){  // name 图片名称，url 图片地址
    // document.getElementById('navigate_name').innerHTML = name || ''
    
    if(url) {
      await this.File_new.new_handler({
        width: 200,
        height: 200,
        resolution_type: 'Custom',
        layout: 'Custom',
        transparency: false,
      })
      this.File_open.file_open_data_url_handler(url)
      if(typeof this.on_change_callback == 'function') this.on_change_callback(name, url)
    }
    else {
      message.open({
        key: this.name,
        type: 'black',
        content: `加载失败，图片地址为空`,
        duration: 2
      })
    }
  }

  styleObjectToString(styleObj) {
    return Object.entries(styleObj)
          .map(([key, value]) => `${key.replace(/([A-Z])/g, '-\$1').toLowerCase()}: ${value};`)
          .join(' ');
  }

  render_compare(){
    let main_wrapper_el = document.getElementById('main_wrapper'),
        main_wrapper_el_rect = main_wrapper_el.getBoundingClientRect(),
        root_style = {
          left: main_wrapper_el_rect.left + 'px',
          top: main_wrapper_el_rect.top + 'px',
          width: main_wrapper_el_rect.width + 'px',
          height: main_wrapper_el_rect.height + 'px',
          zIndex: 108,
          display: 'none'
        };

    let template = `
      <button class="layer_icon layer_text trn compare_close" id="compare_close">关闭对比</button>
      <div class="compare_wrapper">
        <canvas id="compare_old"></canvas>
      </div>
      <div class="compare_wrapper">
        <canvas id="compare_new"></canvas>
      </div>
    `

    let id = 'dialog_compare',
        root_element = document.getElementById(id);

    root_element = document.createElement('div');
    root_element.className = 'dialog_compare'
    root_element.id = 'dialog_compare'
    root_element.style = this.styleObjectToString(root_style)
    root_element.innerHTML = template;
    document.body.appendChild(root_element)
    this.compare_root_el = root_element
    return root_element;
  }

  async get_canvas_main_image(){
    //if IE 11 or Edge
    function is_edge_or_ie() {
      //ie11
      if( !(window.ActiveXObject) && "ActiveXObject" in window )
        return true;
      //edge
      if( navigator.userAgent.indexOf('Edge/') != -1 )
        return true;
      return false;
    }

    return new Promise((resolve) => {
      var tempCanvas = document.createElement("canvas");
      var tempCtx = tempCanvas.getContext("2d");
      var dim = this.Base_layers.get_dimensions();
      tempCanvas.width = dim.width;
      tempCanvas.height = dim.height;
      this.Base_layers.convert_layers_to_canvas(tempCtx);
      
      const image = new Image();
      if(is_edge_or_ie() == false){
        //update image using blob (faster)
        tempCanvas.toBlob(function (blob) {
          const url = URL.createObjectURL(blob);
          image.src = url;
          image.onload = () => {
            resolve(image)
            URL.revokeObjectURL(url)
            image.remove()
          };
          document.body.appendChild(image)
        }, 'image/png');
      }
      else{
        //slow way for IE, Edge
        image.src = tempCanvas.toDataURL();
        image.onload = () => {
          resolve(image)
          image.remove()
        };
      }
      document.body.appendChild(image)
    })
  }

  async open_compare(){
    if (!this.get_layer_is_image()) {
      message.open({
        key: this.name,
        type: 'black',
        content: `非图片类型暂不支持，请选择类型为图片的图层`,
        duration: 2
      })
      return;
    }


    let main_wrapper_el = document.getElementById('main_wrapper'),
        main_wrapper_el_rect = main_wrapper_el.getBoundingClientRect();

    let compare_root_el = this.compare_root_el,
        canvas_old_el = document.getElementById('compare_old'),
        canvas_new_el = document.getElementById('compare_new');

    canvas_old_el.height = main_wrapper_el_rect.height;
    canvas_old_el.width = main_wrapper_el_rect.width / 2;
    canvas_new_el.height = main_wrapper_el_rect.height;
    canvas_new_el.width = main_wrapper_el_rect.width / 2;

    // 更新布局
    compare_root_el.style.left = main_wrapper_el_rect.left + 'px';
    compare_root_el.style.top = main_wrapper_el_rect.top + 'px';
    compare_root_el.style.width = main_wrapper_el_rect.width + 'px';
    compare_root_el.style.height = main_wrapper_el_rect.height + 'px';
    compare_root_el.style.display = '';
    this.is_compare_visible = true

    // 旧
    canvas_old_el.parentNode.classList.add('loading')
    this.compare_module_old = this.load_compare_module(canvas_old_el, config.layer.link_origin, this.compare_module_old)
    canvas_old_el.parentNode.classList.remove('loading')

    // 新
    canvas_new_el.parentNode.classList.add('loading')
    var canvas_main_image = await this.get_canvas_main_image()
    this.compare_module_old = this.load_compare_module(canvas_new_el, canvas_main_image, this.compare_module_old)
    canvas_new_el.parentNode.classList.remove('loading')
  }

	
	/**
	 * 计算缩放值
	 * 
	 * @param {int} recalc 相对缩放值
	 * @param {int} current_zoom 当前缩放值
	 */
  calc_zoom(recalc, current_zoom = 1) {
		if (recalc != undefined) {
			//zoom-in or zoom-out
			if (recalc == 1 || recalc == -1) {
				//fix
				if (current_zoom > 1 && current_zoom < 1.5) {
					current_zoom = 1;
				}
				if (current_zoom > 0.9 && current_zoom < 1) {
					current_zoom = 1;
				}

				//calc step
				if (recalc < 0) {
					//down
					if (current_zoom > 3) {
						//infinity -> 300%
						current_zoom -= 1;
					}
					else if (current_zoom > 1) {
						//300% -> 100%
						current_zoom -= 0.5;
					}
					else if (current_zoom > 0.1) {
						//100% -> 10%
						current_zoom -= 0.1;
					}
					else {
						//10% -> 1%
						current_zoom -= 0.01;
					}
				}
				else {
					//up
					if (current_zoom < 0.1) {
						//1% -> 10%
						current_zoom += 0.01;
					}
					else if (current_zoom < 1) {
						//10% -> 100%
						current_zoom += 0.1;
					}
					else if (current_zoom < 3) {
						//100% -> 300%
						current_zoom += 0.5;
					}
					else {
						//300% -> more
						current_zoom += 1;
					}
				}
			}
			else {
				//zoom using exact value
				current_zoom = recalc / 100;
			}
			current_zoom = Math.round(current_zoom * 100) / 100;
			current_zoom = Math.max(current_zoom, 0.01);
			current_zoom = Math.min(current_zoom, 500);
		}
    return current_zoom
  }

	set_zoom_position(event) {
		var mouse_x = event.offsetX;
		var mouse_y = event.offsetY;
		if (event.changedTouches) {
			//touch events
			event = event.changedTouches[0];

			mouse_x = event.pageX - this.canvas_offset.x;
			mouse_y = event.pageY - this.canvas_offset.y;
		}

    return {

    }
	}

  async load_compare_module(canvas, image, event){
    event = event || {}
    let ctx = canvas.getContext('2d');

    let image_size_new = this.Helper.get_image_size({
      containerWidth: canvas.width,
      containerHeight: canvas.height,
      naturalWidth: image.width,
      naturalHeight: image.height,
    }, 'contain')

    let render_data = {
      x: (canvas.width - image_size_new.width) / 2,
      y: (canvas.height - image_size_new.height) / 2,
      zoom: 1,
      mouse_pressed: false,
      image: image,
    }

    let start_data = {
      init_x: render_data.x,
      init_y: render_data.y,
      x: 0,
      y: 0
    }

    ctx.drawImage(render_data.image, render_data.x, render_data.y, image_size_new.width * render_data.zoom, image_size_new.height * render_data.zoom)

    // 滚动缩放
    if(typeof event.wheel == 'function') document.removeEventListener('wheel', event.wheel)
    let event_wheel = document.addEventListener('wheel', (e) => {
      e.preventDefault();

      if(e.target == canvas){
        var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail || -e.deltaY)));
        var new_zoom = this.calc_zoom(delta > 0 ? +1 : -1, render_data.zoom);
        var diff_zoom = (new_zoom - render_data.zoom) / render_data.zoom;

        render_data.x = render_data.x - (((e.offsetX - render_data.x) * diff_zoom));
        render_data.y = render_data.y - (((e.offsetY - render_data.y) * diff_zoom));   
        render_data.zoom = new_zoom

        ctx.clearRect(0, 0, canvas.width, canvas.height)
        ctx.drawImage(render_data.image, render_data.x, render_data.y, image_size_new.width * render_data.zoom, image_size_new.height * render_data.zoom)
      }
		}, { passive: false });

    // 拖拽移动
    if(typeof event.mousedown == 'function') document.removeEventListener('mousedown', event.mousedown)
		let event_mousedown = document.addEventListener('mousedown', (e) => {
      if(e.target == canvas){   // 点击画布才能开始
        render_data.mouse_pressed = true;
  
        start_data.init_x = render_data.x
        start_data.init_y = render_data.y
        start_data.x = e.x
        start_data.y = e.y
      }
		}, false);

    if(typeof event.mousemove == 'function') document.removeEventListener('mousemove', event.mousemove)
		let event_mousemove = document.addEventListener('mousemove', (e) => {
			if (!render_data.mouse_pressed) return;

      render_data.x = start_data.init_x + (e.x - start_data.x)
      render_data.y = start_data.init_y + (e.y - start_data.y)
      
      ctx.clearRect(0, 0, canvas.width, canvas.height)
      ctx.drawImage(render_data.image, render_data.x, render_data.y, image_size_new.width * render_data.zoom, image_size_new.height * render_data.zoom)
		}, false);
    
    if(typeof event.mouseup == 'function') document.removeEventListener('mouseup', event.mouseup)
		let event_mouseup = document.addEventListener('mouseup', (e) => {
			render_data.mouse_pressed = false;
		}, false);

    return {
      wheel: event_wheel,
      mousedown: event_mousedown,
      mousemove: event_mousemove,
      mouseup: event_mouseup,
    }
  }

  close_compare(){
    if(this.compare_root_el instanceof HTMLElement) this.compare_root_el.style.display = 'none'
    this.is_compare_visible = false
  }

  toggle_compare(visible){
    visible = !!visible
    if(visible) this.open_compare()
    else this.close_compare()
  }
  
  on_compare(){
    this.toggle_compare(!this.is_compare_visible)
  }

  on_prev(){
    if(this.pager.index == 0) return message.open({
      key: this.name,
      type: 'black',
      content: `已经是第一张了`,
      duration: 2
    })

    this.toggle_compare(false)
    this.update_pager((this.pager.index == 0) ? this.pager.count-1 : this.pager.index-1)
    if(typeof this.on_prev_callback == 'function') this.on_prev_callback(this.pager.index, this.load_image.bind(this))
  }

  on_next(){
    if(this.pager.index >= this.pager.count-1) return message.open({
      key: this.name,
      type: 'black',
      content: `已经是最后一张了`,
      duration: 2
    })

    this.toggle_compare(false)
    this.update_pager((this.pager.index == this.pager.count-1) ? 0 : this.pager.index+1)
    if(typeof this.on_prev_callback == 'function') this.on_prev_callback(this.pager.index, this.load_image.bind(this))
  }

  on_save(){
    if(typeof this.on_save_callback == 'function') this.on_save_callback(this.pager.index, this.load_image.bind(this), this.update_pager.bind(this))
  }

  on_close(){
    if(typeof this.on_close_callback == 'function') this.on_close_callback(this.pager.index, this.load_image.bind(this))
  }
}

export default GUI_navigate_class;
